package com.hhkj.admin.bank.service.extend.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.hhkj.admin.bank.common.component.creator.BankCreator;
import com.hhkj.admin.bank.common.component.supplier.BankSupplier;
import com.hhkj.admin.bank.common.cont.BankConst;
import com.hhkj.admin.bank.domain.Bank;
import com.hhkj.admin.bank.domain.BankRule;
import com.hhkj.admin.bank.model.dopo.BankDo;
import com.hhkj.admin.bank.model.dopo.BankPo;
import com.hhkj.admin.bank.model.req.BankReq;
import com.hhkj.admin.bank.model.res.BankRes;
import com.hhkj.admin.bank.service.base.BankService;
import com.hhkj.admin.bank.service.extend.BankExtendService;
import com.hhkj.admin.bank.service.extend.BankQuestionAssoExtendService;
import com.hhkj.admin.question.model.req.QuestionReq;
import com.hhkj.admin.question.model.res.QuestionRes;
import com.hhkj.admin.question.service.extend.QuestionExtendService;
import com.ruoyi.common.base.biz.service.extend.BaseExtendServiceImpl;
import com.ruoyi.common.cont.SysConst;
import com.ruoyi.common.exception.GlobalErrorListException;
import com.ruoyi.common.exception.GlobalException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * BankServiceExtendImpl
 *
 * @author HHKJ-SERVER-ZJ
 * @since 2023/6/8 11:29
 */
@Service
public class BankExtendServiceImpl
        extends BaseExtendServiceImpl<Bank, BankDo, BankPo, BankService>
        implements BankExtendService
{
    @Autowired
    private QuestionExtendService questionExtendService;
    @Autowired
    private BankQuestionAssoExtendService questionAssoExtendService;
    @Autowired
    private BankSupplier supplier;

    @Override
    public List<BankPo> listPublishPoByRuleIdList(List<Long> ruleIdList, String typeCode)
    {
        if (CollectionUtil.isEmpty(ruleIdList)) {
            return new ArrayList<>();
        }
        BankDo bankDo = new BankDo();
        bankDo.setRuleIdList(ruleIdList);
        bankDo.setTypeCode(typeCode);
        bankDo.setPublishFlag(SysConst.Flag.IS.getFlag());
        return this.getService().listPoByDo(bankDo);
    }

    @Override
    public void prepareBeforePublish(BankRes bankRes, BankRule rulePo)
    {
        // 给题库信息添加题目列表信息
        List<QuestionRes> questionGroupList
                = questionExtendService.listPoGroupByBankId(bankRes.getId());
        bankRes.setQuestionGroupList(questionGroupList);
        this.createPractiseBankIfNull(bankRes, rulePo);
        // 创建测试题库
        this.createTestBankIfNull(bankRes, rulePo);
    }

    /**
     * 获取测试题库信息
     *
     * @param totalBankRes 题目类型
     * @param rulePo       选题规则
     */
    private void createTestBankIfNull(BankRes totalBankRes, BankRule rulePo)
    {
        // 查看是否有对应测试题库的对应规则的题库信息
        BankRes testBankRes
                = this.getBankIncludeQuestionGroupList(totalBankRes.getId(), rulePo.getId(), BankConst.Type.TEST.getCode());
        if (ObjectUtil.isNotNull(testBankRes)) {
            return;
        }
        BankReq testBankReq = BankCreator.createTestBank(totalBankRes, rulePo, totalBankRes.getQuestionGroupList());
        List<String> testBankMatchErrorInfoList = rulePo.matchBankErrorInfo(testBankReq);
        if (CollectionUtil.isNotEmpty(testBankMatchErrorInfoList)) {
            throw new GlobalErrorListException(testBankMatchErrorInfoList);
        }
        this.save(testBankReq);
    }

    /**
     * 获取练习题库信息
     *
     * @param bankRes 题库信息
     * @param rulePo  规则信息
     */
    private void createPractiseBankIfNull(BankRes bankRes, BankRule rulePo)
    {
        // 查看是否有对应练习题库的对应规则的题库信息
        BankRes practiseBank
                = this.getBankIncludeQuestionGroupList(bankRes.getId(), rulePo.getId(), BankConst.Type.PRACTISE.getCode());
        if (ObjectUtil.isNotNull(practiseBank)) {
            return;
        }
        BankReq bankReq = BankCreator.createPractiseBank(bankRes, rulePo, bankRes.getQuestionGroupList());
        this.save(bankReq);
    }

    @Override
    public void updateBatchPublishFlagByCourseIdAndCourseBankType(Long courseId, Long courseBankTypeId, Integer publishFlag)
    {
        LambdaUpdateWrapper<Bank> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Bank::getCourseId, courseId)
                .eq(Bank::getCourseBankTypeId, courseBankTypeId)
                .set(Bank::getPublishFlag, publishFlag);
        this.getService().update(updateWrapper);
    }

    @Override
    public BankRes getBankIncludeQuestionGroupList(Long parentId, Long ruleId, String typeCode)
    {
        LambdaQueryWrapper<Bank> queryWrapper = new LambdaQueryWrapper<Bank>()
                .eq(Bank::getParentId, parentId)
                .eq(Bank::getRuleId, ruleId)
                .eq(Bank::getTypeCode, typeCode);
        Bank bankPo = this.getService().getOne(queryWrapper, false);
        BankRes result = BeanUtil.toBean(bankPo, BankRes.class);
        supplier.supplyQuestionList(result);
        return result;
    }

    @Override
    public List<BankRes> listResIncludeQuestionListByRule(BankRule bankRule)
    {
        // 获取上线的对应类型题目信息
        BankDo bankDo = new BankDo();
        bankDo.setCourseParentId(bankRule.getCourseParentId());
        bankDo.setPublishFlag(SysConst.Flag.IS.getFlag());
        bankDo.setCourseBankTypeId(bankRule.getCourseBankTypeId());

        List<BankPo> totalBankList = this.getService().listPoByDo(bankDo);
        if (CollectionUtil.isEmpty(totalBankList)) {
            return new ArrayList<>();
        }
        List<BankRes> resultList = BeanUtil.copyToList(totalBankList, BankRes.class);
        supplier.supplyQuestionList(resultList);
        return resultList;
    }

    @Override
    public boolean removeByParentIdList(List<Long> parentIdList)
    {
        // 删除对应的测试题库和练习题库
        LambdaQueryWrapper<Bank> bankQuery = new LambdaQueryWrapper<>();
        bankQuery.in(Bank::getParentId, parentIdList);
        return this.getService().remove(bankQuery);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveBatch(List<BankReq> reqList)
    {
        List<Bank> bankDoList = new ArrayList<>(reqList);
        boolean result = this.getService().saveBatch(bankDoList);
        if (result) {
            List<QuestionReq> questionList = new ArrayList<>();
            for (BankReq req : reqList) {
                if (BankConst.Type.TOTAL.getCode().equals(req.getTypeCode())) {
                    questionList.addAll(req.getQuestionGroupList());
                }
            }
            if (CollectionUtil.isNotEmpty(questionList)) {
                // 保存题目信息
                questionExtendService.saveBatchGroup(questionList);
            }
            // 保存题目关联信息
            questionAssoExtendService.saveBatchForBank(reqList);
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(BankReq req)
    {
        boolean result = this.getService().save(req);
        if (result) {
            if (BankConst.Type.TOTAL.getCode().equals(req.getTypeCode())) {
                // 保存题目信息
                questionExtendService.saveBatchGroup(req.getQuestionGroupList());
            }
            // 保存题目关联信息
            questionAssoExtendService.saveForBank(req);
        }
        return result;
    }

    @Override
    public BankRes getPublishBank(Long courseId, Long courseBankTypeId, String typeCode)
    {
        LambdaQueryWrapper<Bank> bankQuery = new LambdaQueryWrapper<>();
        bankQuery.eq(Bank::getCourseId, courseId)
                .eq(Bank::getCourseBankTypeId, courseBankTypeId)
                .eq(Bank::getTypeCode, typeCode)
                .eq(Bank::getPublishFlag, SysConst.Flag.IS.getFlag());
        Bank bankPo = this.getService().getOne(bankQuery, false);
        if (ObjectUtil.isNull(bankPo)) {
            throw new GlobalException("题库暂未上架，请联系管理员");
        }
        return BeanUtil.toBean(bankPo, BankRes.class);
    }

    @Override
    public BankRes getResById(Long id)
    {
        Bank bankPo = this.getService().getById(id);
        if (ObjectUtil.isNull(bankPo)) {
            throw new GlobalException("题库不存在！");
        }
        return BeanUtil.toBean(bankPo, BankRes.class);
    }

    @Override
    public BankRes getByParentIdAndTypeCode(Long parentId, String typeCode)
    {
        LambdaQueryWrapper<Bank> bankQuery = new LambdaQueryWrapper<>();
        bankQuery.eq(Bank::getParentId, parentId)
                .eq(Bank::getTypeCode, typeCode);
        Bank bankPo = this.getService().getOne(bankQuery, false);
        if (ObjectUtil.isNull(bankPo)) {
            throw new GlobalException("题库暂未上架，请联系管理员");
        }
        return BeanUtil.toBean(bankPo, BankRes.class);
    }
}